using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Sockets;
using SharpCommunications.Cryptography;
using SharpCommunications.Interfaces;
using SharpCommunications.Connection;
using SharpCommunications.Logging;
using System.Threading;
using System.Text;
using System.Runtime.Serialization;

using SharpCommunications.Serialization;

namespace SharpCommunications.TestClient
{
    [DataContract(IsReference = true)]
    public class Entity 
    {
        public Entity(string name = null, string description = null, string entityType = null)
        {
            this.Id = Guid.NewGuid();
            this.Name = name;
            this.Description = description;
            this.EntityType = entityType;
            this.Properties = new Dictionary<string, object>();
        }

        #region IEntity Members

        [DataMember]
        public string Name { get; set; }
        [DataMember]
        public string Description { get; set; }
        [DataMember]
        public string EntityType { get; set; }
        [DataMember]
        public Guid Id { get; set; }
        [DataMember]
        public Dictionary<string, object> Properties { get; set; }

        #endregion
    }

	class TestClient_Program
	{
	    private static int port;
	    private static string machineName;
	    private static bool quit = false;

	    private static string longMessage;

        static TestClient_Program()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("long message: ");

            for(int k = 0; k < 20000; k++)
            {
                sb.Append('a');
            }

            longMessage = sb.ToString();
        }

        static void Test()
        {
            ISharpSerializer serializer = new DefaultSerializer();

            Entity originalEntity = new Entity() {Description = "My Entity", EntityType = "Type 1", Name = "Entity1"};
            string data = serializer.Serialize(originalEntity, typeof (Entity));

            Entity deserializedEntity = serializer.Deserialize<Entity>(data, typeof (Entity));
            
        }

		[STAThread]
		static void Main(string[] args)
		{
            Test();

		    Location location = new Location("TestClient_Program.Main()");

		    if (args.Length < 2 || args.Length > 3)
		    {
		        Console.WriteLine("USAGE: SharpCommunications.TestClient <machine> <port> [start]\n");
		        return;
		    }

		    machineName = args[0];
		    port = Convert.ToInt32(args[1]);
		    bool start = false;

            if(args.Length == 3 && args[2] == "start")
            {
                start = true;
            }

		    LogFactory.Log.InfoMessage(location,
		                               "SharpCommunications.TestClient_Program. \nInput: \n    Machine Name: {0}\n    Port: {1}",
		                               machineName, port);

            if(start)
            {
                string[] cmdArgs = Environment.GetCommandLineArgs();

                string exePath = cmdArgs[0];

                Process process = new Process();
                process.StartInfo.FileName = exePath;
                process.StartInfo.Arguments = string.Format("{0} {1}", machineName, port);
                process.Start();
            }

   		    Thread.Sleep(1000);

		    Run();
        }

        static void Run()
        {
            Location location = new Location("TestClient_Program.Run()");

            using (SharpChannelClient client = new SharpChannelClient(machineName, port, "sharp_channel.key"))
            {
                client.OnReceive += new ReceivedMessageHandlerDelegate(client_OnReceive);

                Thread.Sleep(1000);

                client.SendMessage("Client message 1");
                Thread.Sleep(1300);

                client.SendMessage(longMessage);
                Thread.Sleep(1300);

                client.SendMessage("quit");
                Thread.Sleep(1000);

                client.SendMessage("Client message 3");
                Thread.Sleep(3000);

                client.SendMessage("Client message 4");
                Thread.Sleep(3000);


                Console.Write("Press 'q' to terminate: ");

                string input;

                while ((input = Console.ReadLine()) != "q")
                {
                    Console.Write("Press 'q' to terminate: ");
                }

                client.SendMessage("quit");

                quit = true;
                Thread.Sleep(10000);
            }
        }

        static void client_OnReceive(ISharpConnectionEndpoint connectionEndpoint, string message)
        {
            Location location = new Location("TestClient_Program.client_OnReceive()");

            if (message.StartsWith("long message"))
            {
                LogFactory.Log.InfoMessage(location, "RECEIVED: {0}", message.Substring(0, 50) + "...");

                if (message == longMessage)
                {
                    LogFactory.Log.InfoMessage(location, "LONG MESSAGE MATCHES THE ORIGINAL");
                }
                else
                {
                    LogFactory.Log.InfoMessage(location, "LONG MESSAGE DOES NOT MATCH THE ORIGINAL");
                }
            }
            else
            {
                LogFactory.Log.InfoMessage(location, "RECEIVED: {0}", message);
            }
        }

	}
}
